import patchVnode from './patchVnode'
import createElement from './createElement'

// 判断是否是同一个虚拟节点
function checkSameVnode(a, b) {
  return a.sel == b.sel && a.key == b.key
}

export default function updateChildren(parentElm, oldCh, newCh) {
  // 旧前
  let oldStartIdx = 0
  // 新前
  let newStartIdx = 0
  // 旧后
  let oldEndIdx = oldCh.length - 1
  // 新后
  let newEndIdx = newCh.length - 1
  // 旧前节点
  let oldStartVnode = oldCh[0]
  // 旧后节点
  let oldEndVnode = oldCh[oldEndIdx]
  // 新前节点
  let newStartVnode = newCh[0]
  // 新后节点
  let newEndVnode = newCh[newEndIdx]

  let keyMap = null

  // 开始循环判断
  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    console.log(123)
    // 一开始先略过undefined
    if (oldStartVnode == null || oldCh[oldStartIdx] == undefined) {
      oldStartVnode = oldCh[++oldStartIdx]
    } else if (oldEndVnode == null || oldCh[oldEndIdx] == undefined) {
      oldEndVnode = oldCh[--oldEndIdx]
    } else if (newStartVnode == null || newCh[newStartIdx] == undefined) {
      newStartVnode = newCh[++newStartIdx]
    } else if (newEndVnode == null || newCh[newEndIdx] == undefined) {
      newEndVnode = oldCh[--newEndIdx]
    } else if (checkSameVnode(oldStartVnode, newStartVnode)) {
      // 新前和旧前
      // 对比节点
      patchVnode(oldStartVnode, newStartVnode)
      oldStartVnode = oldCh[++oldStartIdx]
      newStartVnode = newCh[++newStartIdx]
      // 新后和旧后
    } else if (checkSameVnode(oldEndVnode, newEndVnode)) {
      patchVnode(oldEndVnode, newEndVnode)
      oldEndVnode = oldCh[--oldEndIdx]
      newEndVnode = newCh[--newEndIdx]
      // 新后和旧前
    } else if (checkSameVnode(newEndVnode, oldStartVnode)) {
      console.log('新后和旧前')
      patchVnode(newEndVnode, oldStartVnode)
      // 当新后和旧前命中时,此时要移动节点,移动新前指向的的节点到老节点的旧后后面
      parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling)
      oldStartVnode = oldCh[++oldStartIdx]
      newEndVnode = newCh[--newEndIdx]
      // 新前与旧后
    } else if (checkSameVnode(newStartVnode, oldEndVnode)) {
      console.log('命中新前与旧后')
      patchVnode(newStartVnode, oldEndVnode)
      // 移动新前指向的节点到旧前得的前面
      parentElm.insertBefore(oldEndVnode.elm, oldStartIdx.elm)
      oldEndVnode = oldCh[--oldEndIdx]
      newStartVnode = newCh[++newStartIdx]
    } else {
      // 四种都没有命中
      if (!keyMap) {
        keyMap = {}
        for (let i = oldStartIdx; i <= oldEndIdx; i++) {
          const key = oldCh[i].key
          if (key != undefined) {
            keyMap[key] = i
          }
        }
      }
      // 寻找当前这项(newStartIdx) 这项在keyMap中映射的位置序号
      const idxInOld = keyMap[newStartVnode.key]
      if (idxInOld == undefined) {
        // 表示它是全新的项
        // 被加入的项不是真DOM
        parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm)
      } else {
        // 不是全新的项,而是要移动
        // 将需要移动的项取出来
        const elmToMove = oldCh[idxInOld]

        patchVnode(elmToMove, newStartVnode)
        // 将这项设置为undefined,表示已经处理完了
        oldCh[idxInOld] = undefined
        // 移动,调用insertBefore可以实现移动
        parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm)
      }
      // 指针下移,只移动新的头
      newStartVnode = newCh[++newStartIdx]
    }
  }
  // 剩余节点
  // 循环结束,Start比End小
  if (newStartIdx <= newEndIdx) {
    console.log('剩余节点还没处理,加项')
    // const before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm
    // 遍历新的newCh,添加到老的没处理之前
    for (let i = newStartIdx; i <= newEndIdx; i++) {
      // insertBefore可以自动识别null,如果是null就会自动排到队尾
      parentElm.insertBefore(createElement(newCh[i]), oldCh[oldStartIdx].elm)
    }
  } else if (oldStartIdx <= oldEndIdx) {
    // 批量删除剩余的项
    for (let i = oldStartIdx; i <= oldEndIdx; i++) {
      if (oldCh[i]) {
        parentElm.removeChild(oldCh[i].elm)
      }
    }
  }
}
